package com.suyeer.basic.util;


import de.odysseus.staxon.json.JsonXMLConfig;
import de.odysseus.staxon.json.JsonXMLConfigBuilder;
import de.odysseus.staxon.json.JsonXMLInputFactory;
import de.odysseus.staxon.json.JsonXMLOutputFactory;
import de.odysseus.staxon.xml.util.PrettyXMLEventWriter;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;

import javax.net.ssl.*;
import javax.servlet.http.HttpServletRequest;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

import static org.apache.commons.lang3.StringUtils.defaultIfBlank;

/**
 * @author jun 2018/10/19
 */
public class BasicUtil {

    private final static String LOCAL_IP4 = "127.0.0.1";

    private final static String LOCAL_IP6 = "0:0:0:0:0:0:0:1";

    private final static String UNKNOWN = "unknown";

    private final static String STRING_COMMA = ",";

    private final static int IP_ADDRESS_LENGTH = 15;

    private static AtomicInteger orderIndex = new AtomicInteger(0);
    private final static int MAX_ORDER_INDEX = 999;

    public static String getUserIp(HttpServletRequest request) {
        String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0 || UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (LOCAL_IP4.equals(ipAddress) || LOCAL_IP6.equals(ipAddress)) {
                InetAddress ine = null;
                try {
                    ine = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    LogUtil.error("获取用户ip失败!", e);
                }
                ipAddress = ine.getHostAddress();
            }
        }
        if (ipAddress != null && ipAddress.length() > IP_ADDRESS_LENGTH) {
            if (ipAddress.indexOf(STRING_COMMA) > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }

    public static String getUniqueString() {
        return getUniqueString(StringUtils.EMPTY);
    }

    public static String getUniqueString(String preFixString) {
        String currTimeStr = DateUtil.getShortTimeFormStr(new Date());
        int idx = orderIndex.addAndGet(1);
        if (idx > MAX_ORDER_INDEX) {
            orderIndex.set(0);
            idx = 0;
        }
        return String.format("%s%s%03d%03d", preFixString, currTimeStr, RandomUtils.nextInt(0, MAX_ORDER_INDEX), idx);
    }

    public static String getUUID() {
        return UUID.randomUUID().toString();
    }

    public static String getNonceStr() {
        return EncryptUtil.md5(getUUID());
    }

    public static List<String> getList(String srcStr) {
        return getList(srcStr, ",");
    }

    public static List<String> getList(String srcStr, String separatorStr) {
        List<String> retList = new ArrayList<>();
        if (StringUtils.isNotBlank(srcStr) && separatorStr != null) {
            String[] arr = srcStr.split(separatorStr);
            for (String s : arr) {
                if (StringUtils.isNotBlank(s)) {
                    retList.add(s.trim());
                }
            }
        }
        return retList;
    }

    public static SSLSocketFactory createSSLSocketFactory(String var0, String var1) throws NoSuchAlgorithmException, KeyManagementException, NoSuchProviderException {
        SSLContext sslContext = var1 != null ? SSLContext.getInstance(var0, var1) : SSLContext.getInstance(var0);
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
        sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());
        return sslContext.getSocketFactory();
    }

    public static HostnameVerifier createHostnameVerifier(Boolean verify) {
        return new HostnameVerifier() {
            @Override
            public boolean verify(String s, SSLSession sslSession) {
                return verify;
            }
        };
    }

    public static String hidePhoneNum(String phoneNum) {
        return phoneNum.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
    }

    public static String getReferrer(HttpServletRequest request) {
        return defaultIfBlank(request.getHeader("Referer"), defaultIfBlank(request.getHeader("Referrer"), ""));
    }

    /**
     * json string convert to xml string
     *
     * @param jsonStr String
     * @return String
     */
    public static String json2Xml(String jsonStr) {
        StringReader input = new StringReader(jsonStr);
        StringWriter output = new StringWriter();
        JsonXMLConfig config = new JsonXMLConfigBuilder().multiplePI(false).repairingNamespaces(false).build();
        try {
            XMLEventReader reader = new JsonXMLInputFactory(config).createXMLEventReader(input);
            XMLEventWriter writer = XMLOutputFactory.newInstance().createXMLEventWriter(output);
            writer = new PrettyXMLEventWriter(writer);
            writer.add(reader);
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                output.close();
                input.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //remove <?xml version="1.0" encoding="UTF-8"?>
        if (output.toString().length() >= 38) {
            return output.toString().substring(39);
        }
        return output.toString();
    }

    /**
     * xml string convert to json string
     *
     * @param xml String
     * @return String
     */
    public static String xml2Json(String xml) {
        StringReader input = new StringReader(xml);
        StringWriter output = new StringWriter();
        JsonXMLConfig config = new JsonXMLConfigBuilder().autoArray(true).autoPrimitive(true).prettyPrint(true).build();
        try {
            XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(input);
            XMLEventWriter writer = new JsonXMLOutputFactory(config).createXMLEventWriter(output);
            writer.add(reader);
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                output.close();
                input.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return output.toString();
    }

    public static String getUrlOrigin(String url) {
        if (url.indexOf("/", 8) > 0) {
            url = url.substring(0, url.indexOf("/", 8));
        }
        if (url.indexOf("?") > 0) {
            url = url.substring(0, url.indexOf("?"));
        }
        return url;
    }

    public static String getUrlHost(String url) {
        url = getUrlOrigin(url);
        return url.substring(url.indexOf("//") + 2);
    }

}
